package pe.gob.osinergmin.activity.module;

import android.app.Dialog;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import pe.gob.osinergmin.R;
import pe.gob.osinergmin.activity.generic.GenericBackActionBarActivity;
import pe.gob.osinergmin.bean.common.Usuario;
import pe.gob.osinergmin.utils.PuntoControlConstants;
import pe.gob.osinergmin.utils.PuntoControlMapStateManager;
import pe.gob.osinergmin.utils.PuntoControlUtils;

import static pe.gob.osinergmin.utils.PuntoControlConstants.SESSION_USER_VAR;

public class GPSActivity extends GenericBackActionBarActivity implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {

    private EditText txtPlacaGPS;

    public int _toolbar = R.id.gps_toolbar;

    public static int code = 2;

    private Usuario usuario;

    private GoogleMap mMap;

    private static final float DEFAULT_ZOOM = 15;

    private static final int DEFAULT_PADDING = 50;

    private Location start_position;

    private Location end_position;

    private List<Marker> markerList = new ArrayList<>();

    private GPSActivity gpsActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.module_gps);
        setToolbar((Toolbar) findViewById(_toolbar));
        setSupportActionBar(getToolbar());
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        if(PuntoControlUtils.getProgressDialog().isShowing()){
            PuntoControlUtils.getProgressDialog().dismiss();
        }
        gpsActivity = this;

        usuario = (Usuario)getIntent().getExtras().getSerializable(SESSION_USER_VAR);

        writeStatusBar();

        LinearLayout btnRegresar = (LinearLayout)getToolbar().findViewById(R.id.btnRegresar);
        btnRegresar.setOnClickListener(this);

        ImageView btnBuscarGPS = (ImageView) findViewById(R.id.btnBuscarGPS);
        btnBuscarGPS.setOnClickListener(this);

        txtPlacaGPS = (EditText) findViewById(R.id.txtPlacaGPS);

        if (initMap()) {
            mMap.setMyLocationEnabled(true);
            gotoLocation(getPuntoControlGPSTracker().getLocation().getLatitude(), getPuntoControlGPSTracker().getLocation().getLongitude(),DEFAULT_ZOOM);
        }else{
            showToast(this, R.string.gps_no_map_available, Toast.LENGTH_SHORT);
        }
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.btnRegresar){
            this.finish();
        }
        if(v.getId() == R.id.btnBuscarGPS){
            hideSoftKeyboard(v);

            if(validarGoogleServices()) {
                String placa = txtPlacaGPS.getText().toString();
                if (placa != null && !PuntoControlConstants.EMPTY.equals(placa)) {
                    start_position = getPuntoControlGPSTracker().getLocation();
                    findPositionOnServer(gpsActivity, placa);
                }
            }
        }
    }

    public void findPositionOnServer(final Context context, String placa){
        PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_load_location)).show();

       // Se realiza la busqueda en el servidor
        AsyncHttpClient client = new AsyncHttpClient();
        String url = MessageFormat.format(PuntoControlConstants.URL_GPS_FIND_POSITION_BY_PLACA, placa);
        client.get(url,null ,new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                PuntoControlUtils.getProgressDialog().dismiss();
                try{
                    JSONObject obj = new JSONObject(new String(responseBody));
                    Double latitud = obj.getDouble("latitud");
                    Double longitud = obj.getDouble("longitud");
                    Long fechaRegistro = obj.getLong("fechaRegistro");

                    Location endLocation = new Location(PuntoControlConstants.LOCATION_DUMMY_PROVIDER);
                    endLocation.setLatitude(latitud);
                    endLocation.setLongitude(longitud);
                    endLocation.setTime(fechaRegistro);

                    end_position = endLocation;

                    PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_drawing_map_location)).show();
                    PuntoControlUtils.getProgressDialog().dismiss();

                    drawMarkers(mMap, start_position, end_position);

                } catch (JSONException e) {
                    showToast(context, R.string.error_json_generic, Toast.LENGTH_LONG);
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                PuntoControlUtils.getProgressDialog().dismiss();
                if(statusCode == 404){
                    showToast(context, R.string.error_http_404, Toast.LENGTH_LONG);
                }
                // When Http response code is '500'
                else if(statusCode == 500){
                    showToast(context, R.string.error_http_500, Toast.LENGTH_LONG);
                }
                // When Http response code other than 404, 500
                else{
                    showToast(context, R.string.error_http_other, Toast.LENGTH_LONG);
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.context_menu_gps, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.map_normal:
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;
            case R.id.map_satellite:
                mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;
            case R.id.map_terrain:
                mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;
            case R.id.map_hybrid:
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    private boolean initMap(){
        if( mMap == null ){
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mMap = mapFragment.getMap();
        }
        return (mMap != null);
    }

    private void gotoLocation(double latitud, double longitud, float zoom){
        LatLng latLng = new LatLng(latitud, longitud);
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
        mMap.moveCamera(cameraUpdate);
    }

    private void gotoLocation(LatLngBounds bounds, int padding){
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, padding);
        mMap.moveCamera(cameraUpdate);
    }

    private void writeStatusBar(){
        // Colocando la bienvenida
        TableLayout tableLayout = (TableLayout) findViewById(R.id.gps_status_bar);
        TextView nombre = (TextView) tableLayout.findViewById(R.id.status_bar_nombre);
        String txtNombre = MessageFormat.format(getResources().getString(R.string.menu_welcome), usuario.getNombreCompleto());
        nombre.setText(txtNombre);

        TextView placa = (TextView)tableLayout.findViewById(R.id.status_bar_placa);
        if(PuntoControlConstants.unidadOperativa != null && (!PuntoControlConstants.EMPTY.equals(PuntoControlConstants.unidadOperativa.getPlaca()) && PuntoControlConstants.unidadOperativa.getPlaca() != null)){
            String txtPlaca = MessageFormat.format(getResources().getString(R.string.menu_placa), PuntoControlConstants.unidadOperativa.getPlaca());
            placa.setText(txtPlaca);
        }else{
            placa.setText(PuntoControlConstants.EMPTY);
        }
    }

    private boolean validarGoogleServices(){
        int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

        if(isAvailable == ConnectionResult.SUCCESS){
            return true;
        }else{
            if(GooglePlayServicesUtil.isUserRecoverableError(isAvailable)){
                Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, PuntoControlConstants.GPS_ERRORDIALOG_REQUEST);
                dialog.show();
            }else{
                showToast(this, R.string.gps_cant_connect_play_services, Toast.LENGTH_SHORT);
            }
        }
        return false;
    }

    private void drawMarkers(GoogleMap googleMap, Location startPoint, Location endPoint){
        PuntoControlUtils.getProgressDialog(gpsActivity, getResources().getString(R.string.waiting_drawing_point_location)).show();

        for(Marker marker : markerList){
            marker.remove();
        }
        markerList = new ArrayList<>();

        Marker meMarker = addMarker(googleMap, startPoint.getLatitude(), startPoint.getLongitude(), R.drawable.marker_me, PuntoControlUtils.writeDateFromTime(startPoint.getTime()));
        Marker truckMarker = addMarker(googleMap, endPoint.getLatitude(), endPoint.getLongitude(), R.drawable.marker_truck, PuntoControlUtils.writeDateFromTime(endPoint.getTime()));

        markerList.add(meMarker);
        markerList.add(truckMarker);

        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        builder.include(meMarker.getPosition());
        builder.include(truckMarker.getPosition());

        LatLngBounds bounds = builder.build();

        try {
            gotoLocation(bounds, DEFAULT_PADDING);
        }catch(Exception e){
            e.printStackTrace();
        }

        googleMap.getUiSettings().setZoomControlsEnabled(true);
        googleMap.getUiSettings().setMyLocationButtonEnabled(true);

        PuntoControlUtils.getProgressDialog().dismiss();
    }

    public Marker addMarker(GoogleMap googleMap, double latitude, double longitude, int resourceId, String details){

        // create marker
        MarkerOptions marker = new MarkerOptions();

        // Marker still in position
        marker.draggable(false);

        // Setting position
        marker.position(new LatLng(latitude, longitude));

        // Setting date from register
        marker.title(details);

        // Changing marker icon
        marker.icon(BitmapDescriptorFactory.fromResource(resourceId));

        // adding marker
        return googleMap.addMarker(marker);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(start_position != null && end_position != null) {
            PuntoControlMapStateManager mgr = new PuntoControlMapStateManager(this);
            mgr.saveMapState(mMap, start_position, end_position);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        PuntoControlMapStateManager mgr = new PuntoControlMapStateManager(this);
        start_position =  mgr.getMePosition();
        end_position = mgr.getTruckPosition();
        if (start_position != null) {
            PuntoControlUtils.getProgressDialog(gpsActivity, getResources().getString(R.string.waiting_drawing_map_location)).show();
            PuntoControlUtils.getProgressDialog().dismiss();

            drawMarkers(mMap, start_position, end_position);
            mMap.setMapType(mgr.getSavedMapType());
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
    }

    @Override
    public void onConnected(Bundle arg0) {
//		showToast(this, "Connected to location service", Toast.LENGTH_SHORT);
    }

    @Override
    public void onDisconnected() {
    }
}